package com.java.code.thread;

import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class JavaThreadPool {

    /**
     * 线程池
     * Executors.newSingleThreadExecutor() 单线程池 自始至终都是一个线程
     *
     * @throws InterruptedException
     */
    @Test
    public void testThread2() throws InterruptedException {
        // 4.1) 示例
        ExecutorService executor1 = Executors.newSingleThreadExecutor();
        for (int index = 0; index <= 9; index++) {
            final int count = index;
            executor1.execute(() -> {
                System.out.println("newSingleThreadExecutor单线程池=======" + count);
            });
        }
    }

    /**
     * Executors.newCachedThreadPool() 如果线程池的数量很大 那么会回收无用的线程 如果线程数不足 会创建线程
     * 这种方式虽然可以根据业务场景自动的扩展线程数来处理我们的业务，但是最多需要多少个线程同时处理缺是我们无法控制的；
     * 优点是能实现线程的复用 比如线程1结束了 下一个任务来了 线程1能继续工作
     *
     * @throws InterruptedException
     */
    @Test
    public void testThread3() throws InterruptedException {
        // 4.2) 示例
        ExecutorService executor2 = Executors.newCachedThreadPool();
        for (int index = 0; index <= 9; index++) {
            final int count = index;
            executor2.execute(() -> {
                System.out.println("newCachedThreadPool线程池,当前线程name" + Thread.currentThread().getName() + "=======" + count);
            });
        }
    }

    /**
     * Executors.newFixedThreadPool() 可以指定线程池中的线程数
     *
     * @throws InterruptedException
     */
    @Test
    public void testThread4() throws InterruptedException {
        // 4.3) 示例
        ExecutorService executor3 = Executors.newFixedThreadPool(3);

        for (int index = 0; index <= 9; index++) {
            final int count = index;
            executor3.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("newFixedThreadPool线程池,当前线程name" + Thread.currentThread().getName() + "=======" + count);
                }
            });
        }
    }

    /**
     * Executors.newScheduledThreadPool() 支持定时，以及周期性的任务执行
     *
     * @throws InterruptedException
     */
    @Test
    public void testThread5() throws InterruptedException {
        // 4.4)  示例 initalDelay 延迟第一次执行的时间 period 连续执行之间的时间间隔
        ScheduledExecutorService executor4 = Executors.newScheduledThreadPool(3);

        executor4.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                // 定时任务有一个问题就是 如果执行时间>间隔时间 那么任务执行间隔会错乱
//                Date start = new Date();
//                try {
//                    Thread.sleep(6);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                Date end = new Date();
//                System.out.println("花费时间:"+ (end.getTime()-start.getTime())/1000);
//                System.out.println("结束时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(end));
//
                System.out.println("newScheduledThreadPool线程池,当前线程name" + Thread.currentThread().getName());
            }
        }, 1, 5, TimeUnit.SECONDS);
        Thread.sleep(50000);
    }

    /**
     * 等待线程池的任务执行完毕再继续
     * <p>
     * 拆分任务
     * int size = statSummaryCfgList.size();
     * int theadNumber = 4;
     * List<List<StatSummaryCfg>> list = new ArrayList<>();
     * if (size <= 10 * theadNumber) {//不需要分了
     * list.add(statSummaryCfgList);
     * } else {
     * int divisor = size / theadNumber;
     * int remainder = size % theadNumber;
     * int index = 0;
     * for (; index < theadNumber; index++) {
     * list.add(statSummaryCfgList.subList(index * divisor, (index+1) * divisor));
     * }
     * if(remainder>0){
     * list.add(statSummaryCfgList.subList(index * divisor, size) );
     * }
     * }
     * for(final List<StatSummaryCfg> item : list){
     * executor.execute(new Runnable() {
     *
     * @throws InterruptedException
     * @Override public void run() {
     * executor(item);
     * }
     * });
     * }
     */
    @Test
    public void testThread6() throws InterruptedException {
        ExecutorService executor5 = Executors.newFixedThreadPool(3);
        for (int index = 0; index <= 9; index++) {
            final int count = index;
            //5.1. 提交线程任务
            executor5.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("newFixedThreadPool线程池,当前线程name" + Thread.currentThread().getName() + "=======" + count);
                }
            });
        }
        //5.2. 不在接收新的任务
        executor5.shutdown();
        //5.3. 等待所有线程执行完毕
        executor5.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        System.out.println("所有的线程都执行完毕了!");
    }

}
